package com.tf.integrated.controller;

import com.ccssoft.m8.common.ccssoft.modules.util.EntityWrapperHandle;
import com.ccssoft.m8.common.web.BaseController;
import com.tf.integrated.config.Config;
import com.tf.integrated.config.ResultWebSocketClient;
import com.tf.integrated.config.WarResultWebSocketClient;
import com.tf.integrated.entity.*;
import com.tf.integrated.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.java_websocket.client.WebSocketClient;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;
import java.io.*;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 登录设备接口
 * @author allen
 * @date: 2020年9月14日上午10:56:20
 */
@Api(value = "登录设备接口",description="LoginDeviceController")
@RestController
public class LoginDeviceController extends BaseController
{
    @Autowired
    private SettingInfoService<SettingInfoEntity> settingInfoService;
    @Autowired
    private VehicleStyleService<VehicleStyleEntity> vehicleStyleService;
    @Autowired
    private  DeviceinfoService<DeviceinfoEntity> deviceinfoService;
    @Autowired
    private  ChannelsInfoService<ChannelsInfoEntity> channelsInfoService;
    @Autowired
    private EventresultvehicleinfoService<EventresultvehicleinfoEntity> vehicleService;
    @Autowired
    private EventresultpersonService<EventresultpersonEntity> personService;
    @Autowired
    private EventresulttricyclesinfoService<EventresulttricyclesinfoEntity> tricycleService;
    @Autowired
    private EventresultpedestriansinfoService<EventresultpedestriansinfoEntity> pedestrianService;
    @Autowired
    private EventresultbikesinfoService<EventresultbikesinfoEntity> bikeService;
    @Autowired
    private WarningresultbikepicwarndbtService<WarningresultbikepicwarndbtEntity> bikepicwarndbtService;
    @Autowired
    private WarningresultbikestrwarningstService<WarningresultbikestrwarningstEntity> bikestrwarningstService;
    @Autowired
    private WarningresultfacelibInfodbtService<WarningresultfacelibInfodbtEntity> facelibInfodbtService;
    @Autowired
    private WarningresultfacepicwarndbtService<WarningresultfacepicwarndbtEntity> facepicwarndbtService;
    @Autowired
    private WarningresultpedpicwarndbtService<WarningresultpedpicwarndbtEntity> pedpicwarndbtService;
    @Autowired
    private WarningresultpedstrwarningstService<WarningresultpedstrwarningstEntity> pedstrwarningstService;
    @Autowired
    private WarningresulttripicwarndbtService<WarningresulttripicwarndbtEntity> tripicwarndbtService;
    @Autowired
    private WarningresultvehlicwarndbtService<WarningresultvehlicwarndbtEntity> vehlicwarndbtService;
    @Autowired
    private WarningresultvehpicwarndbtService<WarningresultvehpicwarndbtEntity> vehpicwarndbtService;
    @Autowired
    private WarningresultvehstrwarningstService<WarningresultvehstrwarningstEntity> vehstrwarningstService;
    @Autowired
    private WarningresultfacestrinfodbtService<WarningresultfacestrinfodbtEntity> facestrinfodbtService;
    @Autowired
    private WarningresultbikesinfoService<WarningresultbikesinfoEntity> warningresultbikesinfoService;
    @Autowired
    private WarningresultpersonService<WarningresultpersonEntity> warningresultpersonService;
    @Autowired
    private WarningresultvehicleinfoService<WarningresultvehicleinfoEntity> warningresultvehicleinfoService;
    @Autowired
    private WarningresultpedestriansinfoService<WarningresultpedestriansinfoEntity> warningresultpedestriansinfoService;
    @Autowired
    private WarningresulttricyclesinfoService<WarningresulttricyclesinfoEntity> warningresulttricyclesinfoService;
    //结构化SOCKET
    private static HashMap<String,WebSocketClient> mDevwebsock= new  HashMap<String,WebSocketClient>();
    //结构化SOCKET预警
    private static HashMap<String,WebSocketClient> mDevwebsockwar = new  HashMap<String,WebSocketClient>();

    @ApiOperation("登录设备接口")
    @GetMapping("/logindevice/keep")
    @CrossOrigin(origins = "*",maxAge = 86400)
    public  String logindevicekeep()
    {
        setConfig();
        HttpMethod method = HttpMethod.GET;
        startproxy();
        new Thread(() ->
        {
            try
            {
                Thread.sleep(5 * 1000);
            }
            catch (Exception e)
            {

            }
            goLoginDevice(method);
            while (true)
            {
                try
                {
                    Thread.sleep(45 * 1000);
                    for(Map.Entry<String, String> entry : Config.getmDevToken().entrySet())
                    {
                        HttpHeaders headers = new HttpHeaders();
                        headers.set("X-Token", entry.getValue());
                        try
                        {
                            String rkeep = Config.client(Config.getStarturlpre(entry.getKey())+"/user/keepAlive", method,null, headers);
                            System.out.println("info on  /logindevicekeep rkeep==="+rkeep);
                            parseLoginDevice(rkeep,entry.getKey(),2);
                        }
                        catch (Exception e)
                        {
                            parseLoginDevice("",entry.getKey(),2);
                        }
                    }
                    goLoginDevice(method);

                }
                catch (Exception e)
                {

                }
            }
        }).start();
        return "ok";
    }
    //启动proxy
    private  void startproxy()
    {
        new Thread(() ->
        {
            Config.saveResFile("neuron_proxy",this.getClass().getClassLoader());
            Config.saveResFile("cfgs.ini",this.getClass().getClassLoader());
            try
            {
                Runtime.getRuntime().exec("chmod 755 "+Config.getMproxypath()+"/neuron_proxy");
                Thread.sleep( 1000);
                Runtime.getRuntime().exec("chmod 755 "+Config.getMproxypath()+"/cfgs.ini");
                Thread.sleep( 1000);
                Process proc = Runtime.getRuntime().exec(Config.getMproxypath()+"/neuron_proxy -c "+Config.getMproxypath()+"/cfgs.ini");
                StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "Error");
                StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "Output");
                errorGobbler.start();
                outputGobbler.start();
                proc.waitFor();
            }
            catch (Exception e)
            {
                System.out.println("info on  /startproxy Exception==="+e.getMessage());
            }
        }).start();
    }

    private  void goLoginDevice(HttpMethod method)
    {
        EntityWrapperHandle<DeviceinfoEntity> ew = new EntityWrapperHandle<DeviceinfoEntity>();
        List<DeviceinfoEntity> devinfo  =  deviceinfoService.selectList(ew);
        if(devinfo!=null&&devinfo.size()>0)
        {
            for (int i = 0;i<devinfo.size();++i)
            {
                DeviceinfoEntity  dinfo = devinfo.get(i);
                if(Config.getmCurtoken(dinfo.getDeviceid())==null)
                {
                    Config.setDevurl( dinfo.getDeviceid(),dinfo.getDeviceurl());
                    try
                    {
                        String loginURL =  Config.getStarturlpre(dinfo.getDeviceid())+"/user/login?username=admin&password=admin";
                        System.out.println("info on  /logindevicekeep loginURL==="+loginURL);
                        String rjson = Config.client(loginURL,method,null,null);
                        parseLoginDevice(rjson,dinfo.getDeviceid(),1);
                        getDevchn(dinfo.getDeviceid());
                    }
                    catch (Exception e)
                    {
                        parseLoginDevice("",dinfo.getDeviceid(),1);
                        System.out.println("info on  /logindevicekeep rjson===Exception");
                    }
                }
            }
        }
    }

    private  void getDevchn(String devid)
    {
        HttpMethod method = HttpMethod.GET;
        HttpHeaders headers = new HttpHeaders();
        headers.set("X-Token", Config.getmCurtoken(devid));
        try
        {
            String body = Config.client(Config.getStarturlpre(devid)+"/camera/status", method,null, headers);
            System.out.println("info on  /getDevchn body==="+body);
            if(body!=null&&body.equals("")==false)
            {
                JSONObject jsobj = new JSONObject(body);
                int code   = jsobj.optInt("Code");
                if(code==200)
                {
                    JSONArray dataobj = jsobj.optJSONArray("Data");
                    if(dataobj!=null)
                    {
                        for (int i= 0 ;i<dataobj.length();++i)
                        {
                            JSONObject datajson = (JSONObject)dataobj.get(i);
                            if(datajson.optBoolean("IsOnline")==true)
                            {
                                ChannelsInfoEntity chnety = new ChannelsInfoEntity();
                                chnety.setDeviceid(devid);
                                chnety.setOnline(1);
                                chnety.setChnid(Config.getChannelFromId(datajson.optInt("ChannelNo")));
                                channelsInfoService.insert(chnety);
                            }
                            else
                            {
                                ChannelsInfoEntity chnety = new ChannelsInfoEntity();
                                chnety.setDeviceid(devid);
                                chnety.setOnline(0);
                                chnety.setChnid(Config.getChannelFromId(datajson.optInt("ChannelNo")));
                                channelsInfoService.insert(chnety);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            System.out.println("info on  /getDevchn body===Exception");
        }
    }

    private  void  startWebsocket(DeviceinfoEntity devinfo)
    {
        try
        {
            if(devinfo!=null)
            {
                ResultWebSocketClient webSocketClient = (ResultWebSocketClient)mDevwebsock.get(devinfo.getDeviceid());
                if(webSocketClient!=null)
                {
                    webSocketClient.close();
                    mDevwebsock.remove(devinfo.getDeviceid());
                }
                String prestr = devinfo.getDeviceurl() + "/subscription/analyseResults?chns=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15&fullpic=true";
                webSocketClient = new ResultWebSocketClient(new URI(prestr));
                webSocketClient.setmDevic(devinfo.getDeviceid());
                webSocketClient.setVehicleService(vehicleService);
                webSocketClient.setPersonService(personService);
                webSocketClient.setTricycleService(tricycleService);
                webSocketClient.setPedestrianService(pedestrianService);
                webSocketClient.setBikeService(bikeService);
                webSocketClient.setVehicleStyleService(vehicleStyleService);
                webSocketClient.connect();
                mDevwebsock.put(devinfo.getDeviceid(),webSocketClient);
            }
        }
        catch (Exception e)
        {

        }
    }

    private  void  startwarWebsocket(DeviceinfoEntity devinfo)
    {
        try
        {
            if(devinfo!=null)
            {
                WarResultWebSocketClient webSocketClient = (WarResultWebSocketClient)mDevwebsockwar.get(devinfo.getDeviceid());
                if(webSocketClient!=null)
                {
                    webSocketClient.close();
                    mDevwebsockwar.remove(devinfo.getDeviceid());
                }
                String prestr = devinfo.getDeviceurl() + "/subscription/warningResults?chns=0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15&fullpic=true";
                webSocketClient = new WarResultWebSocketClient(new URI(prestr));
                webSocketClient.setmDevic(devinfo.getDeviceid());
                webSocketClient.setBikepicwarndbtService(bikepicwarndbtService);
                webSocketClient.setBikestrwarningstService(bikestrwarningstService);
                webSocketClient.setFacelibInfodbtService(facelibInfodbtService);
                webSocketClient.setFacepicwarndbtService(facepicwarndbtService);
                webSocketClient.setPedpicwarndbtService(pedpicwarndbtService);
                webSocketClient.setPedstrwarningstService(pedstrwarningstService);
                webSocketClient.setTripicwarndbtService(tripicwarndbtService);
                webSocketClient.setVehlicwarndbtService(vehlicwarndbtService);
                webSocketClient.setVehpicwarndbtService(vehpicwarndbtService);
                webSocketClient.setVehstrwarningstService(vehstrwarningstService);
                webSocketClient.setFacestrinfodbtService(facestrinfodbtService);
                webSocketClient.setWarningresultbikesinfoService(warningresultbikesinfoService);
                webSocketClient.setWarningresultpersonService(warningresultpersonService);
                webSocketClient.setWarningresultvehicleinfoService(warningresultvehicleinfoService);
                webSocketClient.setWarningresultpedestriansinfoService(warningresultpedestriansinfoService);
                webSocketClient.setWarningresulttricyclesinfoService(warningresulttricyclesinfoService);
                webSocketClient.connect();
                mDevwebsockwar.put(devinfo.getDeviceid(),webSocketClient);
            }
        }
        catch (Exception e)
        {

        }
    }

    private  void parseLoginDevice(String body,String devid,int type)
    {
        try
        {
            if(body!=null&&body.equals("")==false)
            {
                JSONObject jsobj = new JSONObject(body);
                int code   = jsobj.optInt("Code");
                if(code==200)
                {
                    JSONObject dataobj = jsobj.optJSONObject("Data");
                    if(dataobj!=null)
                    {
                        String Token = dataobj.optString("Token");
                        Config.setDevToken(devid,Token);
                        logger.error("select on  warning/vehicleAttr Token===" + Token);
                        if(type==1)
                        {
                            EntityWrapperHandle<DeviceinfoEntity> ew = new EntityWrapperHandle<DeviceinfoEntity>();
                            ew.eq("deviceid",devid);
                            List<DeviceinfoEntity> devinfo  = deviceinfoService.selectList(ew);
                            if(devinfo!=null&&devinfo.size()>0)
                            {
                                DeviceinfoEntity updateEnty = devinfo.get(0);
                                updateEnty.setOnline(1);
                                deviceinfoService.update(updateEnty,ew);
                                startWebsocket(updateEnty);
                                startwarWebsocket(updateEnty);
                            }
                        }
                        return;
                    }
                }
            }
        }
        catch (Exception e)
        {

        }
        EntityWrapperHandle<DeviceinfoEntity> ew = new EntityWrapperHandle<DeviceinfoEntity>();
        ew.eq("deviceid",devid);
        List<DeviceinfoEntity> devinfo  = deviceinfoService.selectList(ew);
        if(devinfo!=null&&devinfo.size()>0)
        {
            DeviceinfoEntity updateEnty = devinfo.get(0);
            updateEnty.setOnline(0);
            deviceinfoService.update(updateEnty,ew);
        }
        if(type==1)
        {
            Config.setDevurloffline(devid);
        }
        else if(type==2)
        {
            Config.setDevurloffhead(devid);
        }
    }

    private void setConfig(){
        List<SettingInfoEntity> list = settingInfoService.selectList(new EntityWrapperHandle<>());
        if(list!=null&&list.size()>0){
            Config.setMimgpath(list.get(0).getImgpath());
            Config.setMproxypath(list.get(0).getProxypath());
            Config.setMurlpath(list.get(0).getUrlpath());
            logger.error("imagepath==="+list.get(0).getImgpath()+"===proxypath==="+list.get(0).getProxypath()+"===urlpath==="+list.get(0).getUrlpath());
        }
    }

    public class StreamGobbler extends Thread
    {
        InputStream is = null;
        String type = null;
        public StreamGobbler(InputStream is, String type)
        {
            this.is = is;
            this.type = type;
        }
        public void run()
        {
            try
            {
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while ((line = br.readLine()) != null)
                {
                    if (type.equals("Error"))
                    {
                       // System.out.println("Error   :" + line);
                    }
                    else {
                       // System.out.println("Debug:" + line);
                    }
                }
            } catch (IOException ioe)
            {
                ioe.printStackTrace();
            }
        }
    }
}